package controllers;

import java.sql.SQLException;
import java.util.List;

import models.CommListRequests;
import models.CommunityList;
import models.Exercise;
import models.LogRecord;
import models.Notification;
import models.RegisteredUser;
import models.Request;
import models.RequestOfCommListCreator;
import models.Topic;
import models.Tutorial;
//import models.membersInCommList;
import play.data.validation.Required;
import play.mvc.Controller;

public class CommunityLists extends Controller {

	public static void createCommListPage() // aya marwan: to call page where
											// user create commlist
	{
		render();
	}
	
	/**
	 * this method enable the registeredUser to create communityList
	 * 
	 * @author ayatullah marawan
	 * @param String text
	 *            RegisteredUser mail
	 */

	public static void createCommunityList(@Required String text) {
		if (validation.hasErrors()) {
			flash.error("Oops, please enter community List name!");
			createCommListPage();
		}

		long uid = Long.parseLong(session.get("RegisteredUserId"));
		RegisteredUser user = RegisteredUser.findById(uid);
		CommunityList comList = new CommunityList(text, user);
		user.createdCommLists.add(comList);
		user.save();

		long add = comList.getId();
		// session.put("CreatedCommunityListId", comList.id);
		// long add = Long.parseLong(session.get("CreatedCommunityListId"));
		// String comm = session.get("CreatedCommunityListId");
		// long commList =
		// Long.parseLong(session.get("CreatedCommunityListId"));
		// CommunityList x = CommunityList.findById(comm);
		// x.name = text;
		// x.save();
		// u.getCommList().add(comm);
		// render();
		commListContent(add);
	}

	public static void AddMembersToExistingCommList(long commId) {
		commId = Long.parseLong(session.get("CurrentCommList"));
		CommunityList comm = CommunityList.findById(commId);
		RegisteredUser creatorOfComm = comm.getCreator();
		long userId = Long.parseLong(session.get("RegisteredUserId"));
		RegisteredUser user = RegisteredUser.findById(userId);

		if (creatorOfComm != user) {
			renderText("you can not add members because u are not the creator");
		}

		else {
			addMembersToMyCommList();
		}
	}

	public static void addMembersToMyCommList() {
		long commId = Long.parseLong(session.get("CurrentCommList"));
		CommunityList comm = CommunityList.findById(commId);
		render(comm, commId);
	}

	/**
	 * start @author ayatullah marawan In this user story, the user can search
	 * for other users, where he enters the e-mail of certain user in the search
	 * bar then all users having the same name will show to the user so as to
	 * add them in one of his community lists. end @author Ayatullah MArawan
	 * 
	 * @param texttwo
	 *            RegisteredUser mail
	 */

	public static void searchBymail(@Required String texttwo) {
		if (validation.hasErrors()) {
			flash.error("Oops, please enter e-mail!");
			addMembersToMyCommList();
		}

		long commId = Long.parseLong(session.get("CurrentCommList"));
		CommunityList comm = CommunityList.findById(commId);

		String mail = texttwo;
		List usersByMail = RegisteredUser.find("mail=?", mail).fetch();
		render(usersByMail, comm, commId);
	}

	public static void searchBynameToAdd(@Required String nametext) {
		if (validation.hasErrors()) {
			flash.error("Oops, please enter name!");
			addMembersToMyCommList();
		}

		long commId = Long.parseLong(session.get("CurrentCommList"));
		CommunityList comm = CommunityList.findById(commId);

		String Name = nametext;
		List usersByName = RegisteredUser.find("byNameLike","%"+Name+"%" ).fetch();
		
		render(usersByName, comm, commId);
	}

	/**
	 * start @author ayatullah marawan In this user story, the user can search
	 * for other users, where he clicks on button search for all members then
	 * all users show to the user so as to add them in one of his community
	 * lists. end @author Ayatullah MArawan
	 */

	public static void membersCanAdd() {
		boolean add = true;
		long commId = Long.parseLong(session.get("CurrentCommList"));
		CommunityList comm = CommunityList.findById(commId);
		List usersCanAdd = RegisteredUser.find("order by id desc").fetch();

		render(usersCanAdd, comm, commId, add);
	}

	public static void List(String myList) {
		render(myList);
	}

	/**
	 * start @author ayatullah marawan In this user story, the user can add
	 * other users to be members in one of his community lists that he has
	 * created.Where when he clicks on button add then this method will be check
	 * if the user he is adding is already a member or added him before and he
	 * didn't reply then he will not be able to add him otherwise a request to
	 * join this community list will be sent to the chosen user end @author
	 * Ayatullah MArawan
	 * 
	 * @param add
	 *            RegisteredUSer ID
	 */

	public static void ActionToAdd(long add) // aya marwan :to add others ..
												// send them a request to be
												// member in my communityList
	{
		if (add != 0) {
			long userid = Long.parseLong(session.get("RegisteredUserId"));
			long comm = Long.parseLong(session.get("CurrentCommList"));
			long replier = add;
			List<CommListRequests> alreadymember = CommListRequests
					.find("requesterID=? and replierID=? and CommListId=? and isAccepted=? ",
							userid, replier, comm, true).fetch();
			List<CommListRequests> sentrequestbeforewithnoresponse = CommListRequests
					.find("requesterID=? and replierID=? and CommListId=? and isAccepted=? and isRejected=?",
							userid, replier, comm, false, false).fetch();
			// List<CommListRequests> alreadymember =
			// CommListRequests.find("requesterID=? and replierID=? and CommListId=? and isrejected=? ",
			// userid, replier,comm,true).fetch();

			if (alreadymember.isEmpty()
					&& sentrequestbeforewithnoresponse.isEmpty()
					&& !(replier == userid)) {
				CommListRequests y = new CommListRequests(userid, add, comm);
				RegisteredUser o = RegisteredUser.findById(replier);
				o.requestsToJoinCommList.add(y);
				o.save();

				String name = o.getName();
				renderText("u have successfully added " + name);
			} else if (replier == userid) {
				renderText("u can not add yourself, you are the creator of this communityList");
			} else {
				renderText("u can not add this user, he is either a member or u sent request without and he didnt response");
			}

		}
	}

	/**
	 * This method calculate the score of any community list.
	 * 
	 * @author Ayatullah Marawan
	 * @param long comm
	 */
	public static void viewCommListScore(long comm) {

		comm = Long.parseLong(session.get("CurrentCommList"));
		CommunityList commList = CommunityList.findById(comm);
		List<RegisteredUser> users = commList.getMembersList();
		int sum = 0;

		for (int i = 0; i < users.size(); i++) {
			RegisteredUser u = users.get(i);
			// sum = c.score;
			sum = sum + u.getPoints();
		}
		renderText("score of communityList is" + " "+sum);
	}

	/**
	 * This method able the creator of certain community list to accept any
	 * other members request to join his community List.
	 * 
	 * @author Ayatullah Marawan
	 * @param long accept
	 */
	public static void CreatorAcceptJoiners(long accept) {

		RequestOfCommListCreator request = RequestOfCommListCreator.findById(accept);
		long senderId = request.senderId;
		RegisteredUser joiner = RegisteredUser.findById(senderId);

		long recieverId = request.recieverId;
		RegisteredUser CreatorOfCommList = RegisteredUser.findById(recieverId);

		long commListID = request.commListId;
		CommunityList c = CommunityList.findById(commListID);

		if(request.isAccepted == false && request.isRejected == false)
		{
			joiner.CommunityLists.add(c);
			c.membersList.add(joiner);
			joiner.save();
			c.save();
			request.isAccepted = true;
			request.save();
			CreatorOfCommList.requestsToCreatorCommList.remove(request);
			creatorRequests();
			//renderText(" you accepted this request successfully ");
		}
		else if (request.isAccepted == false && request.isRejected == true)
		{
			renderText("you rejected this request before");
		}
		else if(request.isAccepted == true && request.isRejected == false)
		{
			renderText("you accepted this request before");
		}

	}

	/**
	 * This method takes able the creator of certain community list to reject
	 * any other members request to join his community List.
	 * 
	 * @author Ayatullah Marawan
	 * @param long reject
	 */
	public static void CreatorRejectJoiners(long reject) {

		RequestOfCommListCreator req = RequestOfCommListCreator.findById(reject);
		long recieverId = req.recieverId;
		
		if(req.isAccepted == false && req.isRejected == false)
		{
			RegisteredUser CreatorOfCommList = RegisteredUser.findById(recieverId);
			CreatorOfCommList.requestsToCreatorCommList.remove(req);
			req.isRejected=true;
			req.save();
			creatorRequests();
		}
		else if (req.isAccepted == false && req.isRejected == true)
		{
			renderText("you rejected this request before !!!!!");
		}
		else if(req.isAccepted == true && req.isRejected == false)
		{
			renderText("sorry, you accepted this request before");
		}
		
		
	}

	// Begin ----> Ebaa
	/**
	 * This method makes a member leave a community list if he is the creator of
	 * the community list it checks if the community list has an owner then the
	 * owner will be the creator and if not it calls another method called
	 * assignCreatorAut
	 * 
	 * @author Ebaa
	 * @param commListid
	 *            Community List Id
	 */
	public static void leaveCommunityList(long commListId) {
		long memberId = Long.parseLong(session.get("RegisteredUserId"));
		models.RegisteredUser user = models.RegisteredUser.findById(memberId);
		models.CommunityList commList = models.CommunityList
				.findById(commListId);
		if (memberId == (long) commList.getCreator().id) {
			if (commList.getOwner() == null) {
				assignCreatorAut(commListId);
			} else {
				models.RegisteredUser owner = commList.getOwner();
				commList.setCreator(owner);
				commList.setOwner(null);
				user.getCreatedCommLists().remove(commList);
				owner.getCreatedCommLists().add(commList);
				owner.getOwnerCommunityLists().remove(commList);
				owner.getCommunityLists().remove(commList);
				commList.getMembersList().remove(owner);
				owner.save();
				LogRecord.createLog("Left a community list:  " + commList.name  , user);
				LogRecord.createLog("Assigned as an Owner To: " + commList.name  , owner);
			}
		} else {
			if (user == commList.getOwner()) {
				commList.setOwner(null);
			}

			commList.getMembersList().remove(user);
			user.getCommunityLists().remove(commList);
			LogRecord.createLog("Left a community list:  " + commList.name  , user);
		}
		commList.save();
		user.save();
		viewCommLists(memberId);
	}

	/**
	 * This method renders the members of a community list so that the creator
	 * can choose an owner
	 * 
	 * @author Ebaa
	 * @param commListid
	 *            Community List Id
	 */
	public static void assignOwner(long commListId) {
		List<RegisteredUser> membersList;
		models.CommunityList commList = models.CommunityList
				.findById(commListId);
		membersList = commList.getMembersList();
		RegisteredUser temp;
		for (int i = 0; i < membersList.size(); i++) {

			for (int k = i; k < membersList.size(); k++) {
				if (membersList.get(k).points > membersList.get(i).points) {
					temp = membersList.get(i);
					membersList.set(i, membersList.get(k));
					membersList.set(k, temp);
				}
			}
		}
		render(membersList, commListId);
	}

	/**
	 * This method allows the creator of the community list to choose an owner
	 * and sets the owner of the community list as the chosen user
	 * 
	 * @author Ebaa
	 * @param userId
	 *            Chosen user Id
	 * @param commListid
	 *            Community List Id
	 */
	public static void chooseOwner(long userId, long commListId) {
		long memberId = Long.parseLong(session.get("RegisteredUserId"));
		models.CommunityList commList = models.CommunityList
				.findById(commListId);
		models.RegisteredUser user = models.RegisteredUser.findById(userId);
		commList.setOwner(user);
		user.getOwnerCommunityLists().add(commList);
		user.save();
		commList.save();
		new Notification(memberId, userId, commListId, 16).save();
		LogRecord.createLog("Assigned as an Owner To: " + commList.name  , user);
		viewCommLists(memberId);
	}

	/**
	 * This method allows the creator of the community list to leave the
	 * community list and the system will assign a creator automatically with
	 * the highest points
	 * 
	 * @author Ebaa
	 * @param commListid
	 *            Community List Id
	 */
	public static void assignCreatorAut(long commListId) {
		long memberId = Long.parseLong(session.get("RegisteredUserId"));
		models.RegisteredUser user2 = models.RegisteredUser.findById(memberId);
		models.CommunityList commList = models.CommunityList
				.findById(commListId);
		if (commList.getMembersList().size() != 0) {
			int size = commList.getMembersList().size();
			RegisteredUser user = commList.getMembersList().get(0);
			for (int i = 1; i < size; i++) {
				if (user.getPoints() < commList.getMembersList().get(i)
						.getPoints()) {
					user = commList.getMembersList().get(i);
				}
			}
			commList.setCreator(user);
			user2.getCreatedCommLists().remove(commList);
			user.getCreatedCommLists().add(commList);
			commList.getMembersList().remove(user);
			user.getCommunityLists().remove(commList);
			commList.setOwner(null);
			user.getOwnerCommunityLists().remove(commList);
			commList.save();
			user2.save();
			user.save();
			String name = user.getName();
			new Notification(0, user.id, commListId, 20).save();
			LogRecord.createLog("Assigned as Creator To: " + commList.name  , user);
			renderText(name + " is now the creator of the community list");

		}
		viewCommLists(memberId);
	}

	/**
	 * This method renders the created tutorials of a user so he can choose a
	 * contributor to a specific tutorial
	 * 
	 * @author Ebaa
	 * @param userId
	 *            chosen user Id to be a contributor
	 * 
	 */
	public static void makeContributor(long userId) {
		long memberId = Long.parseLong(session.get("RegisteredUserId"));
		List<Tutorial> tuts = Tutorial.find("creator.id = ?", memberId).fetch();
		render(tuts, userId);
	}

	/**
	 * This method will enable a member of the community list to make another
	 * member a contributor to one of his created tutorials
	 * 
	 * @author Ebaa
	 * @param userId
	 *            chosen user Id to be a contributor
	 * @param tutId
	 *            chosen Tutorial Id
	 */
	public static void makeContributorToTut(long tutId, long userId) {
		long memberId = Long.parseLong(session.get("RegisteredUserId"));
		models.RegisteredUser user = models.RegisteredUser.findById(userId);
		models.Tutorial tutorial = models.Tutorial.findById(tutId);
		user.getContributedTutorials().add(tutorial);
		user.setContributor(true);
		tutorial.getContributorsList().add(user);
		tutorial.save();
		user.save();
		new Notification(memberId, userId, tutorial.id, 3).save();
		LogRecord.createLog("Now Contributor To: " + tutorial.Title  , user);
		viewCommLists(memberId);
	}

	// End -----> Ebaa

	/**
	 * This method renders two types of lists which are the created and the
	 * joined communityLists of a registeredUser after checking whether the
	 * registeredUser wants to view one's communityLists or others
	 * communityLists by using boolean isReg
	 * 
	 * 
	 * @author Heidi ElToukhy
	 * @param long viewOthers
	 */

	public static void viewCommLists(long viewOthers) {

		long x = Long.parseLong(session.get("RegisteredUserId"));
		RegisteredUser user = RegisteredUser.findById(x);

		RegisteredUser userOne = RegisteredUser.findById(viewOthers);

		boolean isReg = false;
		if (x != viewOthers) {

			isReg = false;
			List<CommunityList> ListPage;
			ListPage = userOne.getCreatedCommLists();

			List<CommunityList> ListPage2;
			ListPage2 = userOne.getCommunityLists();

			render(ListPage, ListPage2, isReg);
		}

		else {

			isReg = true;
			List<CommunityList> ListPage;
			ListPage = user.getCreatedCommLists();

			List<CommunityList> ListPage2;
			ListPage2 = user.getCommunityLists();

			render(ListPage, ListPage2, isReg);

		}

	}

	/**
	 * This method takes the id of the button Open to retrieve the communityList
	 * being chosen and renders the regiseteredUser's communityList members
	 * 
	 * 
	 * @author Heidi ElToukhy
	 * @param long Open
	 */
	public static void commListContent(long Open) {

		session.put("CurrentCommList", Open);

		CommunityList x = CommunityList.findById(Open);

		List<RegisteredUser> membersList;
		membersList = x.getMembersList();

		render(membersList, Open, x);

	}

	/**
	 * This method renders a list of the requests received by a registeredUser
	 * for others to join a communityList
	 * 
	 * 
	 * @author Heidi ElToukhy
	 * @param no
	 *            parameters
	 */
	public static void viewCommListRequests() {

		long receiverID = Long.parseLong(session.get("RegisteredUserId"));
		RegisteredUser user = RegisteredUser.findById(receiverID);

		List<CommListRequests> communityRequests = 
		CommListRequests.find("replierID =? and isAccepted =? and isRejected =?",user.id, false, false).fetch();

		render(communityRequests);

	}

	/**
	 * the method allows the user to accept community list invitation and then
	 * add the member to the list of members in the communityList
	 * 
	 * @author Nada
	 * @param accept
	 *            is the button value which refers to the commListRequests
	 */
	public static void accept(long accept) {

		CommListRequests request= CommListRequests.findById(accept);
		long replierId = Long.parseLong(session.get("RegisteredUserId"));
		RegisteredUser user = RegisteredUser.findById(replierId);
		long commListId = request.getCommListId();
		CommunityList commList = CommunityList.findById(commListId);
		if (request.isAccepted == false) {
			user.CommunityLists.add(commList);
			commList.membersList.add(user);
			commList.save();
			user.save();
			request.setAccepted(true);
			request.setRejected(false);
			user.save();
			viewCommListRequests();
		}
		renderText(" you accepted this request before !");
	}

	/**
	 * 
	 * the method allows the user to reject community list
	 * 
	 * @author Nada
	 * @param reject
	 *            which is a button id representing commListRequest id
	 */

	public static void reject(long reject) {
		CommListRequests request = CommListRequests.findById(reject);
		request.setRejected(true);
		request.setAccepted(false);
		request.save();
		viewCommListRequests();
	}


	// Temporary method
	public static void recommendTopic() {
		render();
	}

	/**
	 * This method allows the user to to join others community lists and sends a
	 * request to the creator
	 * @author Nada
	 * @param join
	 *             which represents the id of the community list
	 */

	public static void askToJoin(long join) {
		long senderId = Long.parseLong(session.get("RegisteredUserId"));
		RegisteredUser sender = RegisteredUser.findById(senderId);

		CommunityList communityList = CommunityList.findById(join);
		long recieverId = communityList.getCreator().id;
		RegisteredUser reciever = RegisteredUser.findById(recieverId);
		
		List<RequestOfCommListCreator> sentrequestbeforewithnoresponse = RequestOfCommListCreator
				.find("recieverId=? and senderId=? and commListId=? and isAccepted=? and isRejected=?",
						recieverId, senderId, communityList.id, false, false).fetch();


		if (!communityList.membersList.contains(sender) && sentrequestbeforewithnoresponse.isEmpty() && communityList.getCreator() != sender ) {
			
			RequestOfCommListCreator r = new RequestOfCommListCreator(recieverId,
					senderId, join);
			
			reciever.requestsToCreatorCommList.add(r);
			reciever.save();

			r.setSent(true);
			renderText("Request sent!");

		}
		
		if (communityList.getCreator() == sender) {
			renderText("you can not ask to join you are the creator of this community list");
		} else if (!sentrequestbeforewithnoresponse.isEmpty())
		{
			renderText("u sent request before!");
		}
		else 
		{
			renderText("u are already a member");
		}

	}

	/**
	 * This method if for ONLY the creator where it renders a list of the
	 * received requests from the users to join that creator's communityList
	 * 
	 * 
	 * @author Heidi ElToukhy
	 */
	public static void creatorRequests() {

		long creatorID = Long.parseLong(session.get("RegisteredUserId"));
		RegisteredUser user = RegisteredUser.findById(creatorID);

	
		List<RequestOfCommListCreator> creatorCommRequests = RequestOfCommListCreator.find(
				"recieverId =? and isAccepted =? and isRejected =? ",user.id, false, false).fetch();
		
		render(creatorCommRequests);

	}

	/**
	 * This method takes the commId and renders a list of existing topics,
	 * recommended topics and commId.
	 * 
	 * @param commId
	 *            which is the community list id that I'm standing on.
	 * 
	 * @return a list of topics and recommended topics
	 * 
	 * @throws SQLException
	 * @author mayar
	 */

	public static void recommendedTopic(long commId) throws SQLException {
		CommunityList commList = CommunityList.findById(commId);
		long uId = Long.parseLong(session.get("RegisteredUserId"));
		List<Topic> recommendedTopics = commList.recommendListTopic;
		List<Topic> topics = Topic.findAll();
		render(topics, recommendedTopics, commId);
	}

	/**
	 * This method takes the commId, topicId and checks if the topic that I want
	 * to recommend is already recommended before or not. And if it's not added
	 * it adds it.
	 * 
	 * @param commId
	 *            which is the community list id that I'm standing on.
	 * 
	 * @param topicId
	 *            which is the id of the topic I want to recommend.
	 * 
	 * @return a text confirming whether it is recommended before or not or if
	 *         recommended at all.
	 * 
	 * @author mayar
	 */

	public static void recommendTopic(long commId, long topicId) {

		CommunityList commList = CommunityList.findById(commId);
		Topic topic = Topic.findById(topicId);
		if ((commList.recommendListTopic.contains(topic))) {

			renderText("You have already recommended this topic!");

		} else {

			topic.recommendedTopics.add(commList);
			commList.recommendListTopic.add(topic);

			commList.save();
			topic.save();
			renderText("The topic is recommended successfully! :)");

		}
	}

	/**
	 * This method takes the commId and renders a list of existing tutorials,
	 * recommended tutorials and commId.
	 * 
	 * @param commId
	 *            which is the community list id that I'm standing on.
	 * 
	 * @return a list of tutorials and recommended tutorials
	 * 
	 * @throws SQLException
	 * @author mayar
	 */
	public static void recommendedTutorial(long commId) throws SQLException {
		CommunityList commList = CommunityList.findById(commId);
		long uId = Long.parseLong(session.get("RegisteredUserId"));
		List<Tutorial> recommendTutorials = commList.recommendList;
		List<Tutorial> tutorials = Tutorial.findAll();
		render(tutorials, recommendTutorials, commId);
	}

	/**
	 * This method takes the commId, tutorialId and checks if the tutorial that
	 * I want to recommend is already recommended before or not. And if it's not
	 * added it adds it.
	 * 
	 * @param commId
	 *            which is the community list id that I'm standing on.
	 * 
	 * @param tutorialId
	 *            which is the id of the tutorial I want to recommend.
	 * 
	 * @return a text confirming whether it is recommended before or not or if
	 *         recommended at all.
	 * 
	 * @author mayar
	 */
	public static void recommendTutorial(long commId, long tutorialId) {

		CommunityList commList = CommunityList.findById(commId);
		Tutorial tutorial = Tutorial.findById(tutorialId);
		if ((commList.recommendList.contains(tutorial))) {

			renderText("You have already recommended this tutorial!");

		} else {

			tutorial.recommendedTutorials.add(commList);
			commList.recommendList.add(tutorial);

			commList.save();
			tutorial.save();
			renderText("The tutorial is recommended successfully! :)");

		}
	}

	/**
	 * This method takes the commId and renders a list of existing exercises,
	 * recommended exercises and commId.
	 * 
	 * @param commId
	 *            which is the community list id that I'm standing on.
	 * 
	 * @return a list of exercises and recommended exercises
	 * 
	 * @throws SQLException
	 * @author mayar
	 */

	public static void recommendedExercise(long commId) throws SQLException {
		CommunityList commList = CommunityList.findById(commId);
		long uId = Long.parseLong(session.get("RegisteredUserId"));
		List<Exercise> recommendExercises = commList.recommendListExercise;
		List<Exercise> exercises = Exercise.findAll();
		render(exercises, recommendExercises, commId);
	}

	/**
	 * This method takes the commId, exerciseId and checks if the exercise that
	 * I want to recommend is already recommended before or not. And if it's not
	 * added it adds it.
	 * 
	 * @param commId
	 *            which is the community list id that I'm standing on.
	 * 
	 * @param exerciseId
	 *            which is the id of the exercise I want to recommend.
	 * 
	 * @return a text confirming whether it is recommended before or not or if
	 *         recommended at all.
	 * 
	 * @author mayar
	 */
	public static void recommendExercise(long commId, long exerciseId) {

		CommunityList commList = CommunityList.findById(commId);
		Exercise exercise = Exercise.findById(exerciseId);
		if ((commList.recommendListExercise.contains(exercise))) {

			renderText("You have already recommended this exercise!");

		} else {

			exercise.recommendExercises.add(commList);
			commList.recommendListExercise.add(exercise);

			commList.save();
			exercise.save();
			renderText("The exercise is recommended successfully! :)");

		}
	}

}
